﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using SIO = System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Heroius.Files;

namespace Heroius.BlueMeasure
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            AppVersion.Text = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(4);

            //config loading
            cfolder = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/Heroius/BlueMeasure";
            if (!SIO.Directory.Exists(cfolder)) SIO.Directory.CreateDirectory(cfolder);
            cpath = $"{cfolder}/config.xml";
            Configuration.Default = new Configuration();
            if (SIO.File.Exists(cpath))
            {
                EntitySilo silo = new EntitySilo();
                silo.Load(cpath);
                silo.Fetch("config", Configuration.Default);
            }

            diaimg = new OpenFileDialog();
            diaimg.Filter = "支持的位图|*.jpg;*.png;*.bmp|XAML|*.xaml";
            DataContext = this;
        }

        string cfolder, cpath;

        private void Window_Closing(object sender, CancelEventArgs e)
        {
            EntitySilo silo = new EntitySilo();
            silo.Store("config", Configuration.Default);
            silo.Save(cpath);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChangedEvent(string PropertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
        }

        #region 区域缩放

        /// <summary>
        /// 区域的缩放比例
        /// </summary>
        public double ZoomScale
        {
            get { return _ZoomScale; }
            set
            {
                if (value < 0) _ZoomScale = 0;
                else _ZoomScale = value;

                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ZoomScale"));
            }
        }
        double _ZoomScale = 1;

        private void BtnZoomDown_Click(object sender, RoutedEventArgs e)
        {
            ZoomScale -= 0.01;
        }

        private void BtnZoomUp_Click(object sender, RoutedEventArgs e)
        {
            ZoomScale += 0.01;
        }

        private void ScrollViewer_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            var s = sender as ScrollViewer;
            if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
            {
                s.ScrollToVerticalOffset(s.VerticalOffset - e.Delta);
            }
            else if ((Keyboard.Modifiers & ModifierKeys.Alt) > 0)
            {
                s.ScrollToHorizontalOffset(s.HorizontalOffset - e.Delta);
            }
            else
            {
                ZoomScale += (e.Delta / 10000.0);
            }
            e.Handled = true;
        }

        private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            //阻止系统的alt处理，避免在使用alt+wheel进行横向滚动后，焦点丢失的情况
            if (e.SystemKey == Key.RightAlt || e.SystemKey == Key.LeftAlt)
            {
                e.Handled = true;
            }
        }

        #endregion

        #region 图像加载

        OpenFileDialog diaimg;
        private void BtnPic_Click(object sender, RoutedEventArgs e)
        {
            if (diaimg.ShowDialog() == true)
            {
                XamlBlue.Children.Clear(); //clear xaml obj to release resources
                switch (diaimg.FilterIndex)
                {
                    case 1: //bitmap images
                        ImgBlue.Visibility = Visibility.Visible;
                        XamlBlue.Visibility = Visibility.Collapsed;
                        ImgBlue.Source = new BitmapImage(new Uri(diaimg.FileName));
                        break;
                    case 2: //xaml elements
                        ImgBlue.Visibility = Visibility.Collapsed;
                        XamlBlue.Visibility = Visibility.Visible;
                        var o = (UIElement)XamlReader.Load(diaimg.OpenFile());
                        XamlBlue.Children.Add(o);
                        break;
                }
                ImageLoaded = true;
                ScaleSet = false;
                ScaleRecords.Clear();
                MeasureRecords.Clear();
                DrawingPanel.Children.Clear();
                RaiseUIPropertyChanged();
            }
        }

        string[] SupportedFileExtensions = new string[] {
            ".jpg", ".bmp", ".png", ".xaml"
        };

        //文件拖放
        private void Grid_Drop(object sender, DragEventArgs e)
        {
            string[] files = (string[])e.Data.GetData(DataFormats.FileDrop, true);
            if (files != null && files.Length > 0)
            {
                for (int i = 0; i < files.Length; i++)
                {
                    var fi = new SIO.FileInfo(files[i]);
                    var ext = fi.Extension;
                    if (SupportedFileExtensions.Contains(fi.Extension.ToLower()))
                    {
                        XamlBlue.Children.Clear(); //clear xaml obj to release resources
                        switch (ext)
                        {
                            case ".xaml": //xaml elements
                                ImgBlue.Visibility = Visibility.Collapsed;
                                XamlBlue.Visibility = Visibility.Visible;
                                var o = (UIElement)XamlReader.Load(fi.Open(SIO.FileMode.Open));
                                XamlBlue.Children.Add(o);
                                break;
                            default: //bitmap images
                                ImgBlue.Visibility = Visibility.Visible;
                                XamlBlue.Visibility = Visibility.Collapsed;
                                ImgBlue.Source = new BitmapImage(new Uri(fi.FullName));
                                break;
                        }
                        ImageLoaded = true;
                        ScaleSet = false;
                        ScaleRecords.Clear();
                        MeasureRecords.Clear();
                        DrawingPanel.Children.Clear();
                        RaiseUIPropertyChanged();
                    }
                }
            }
        }

        #endregion

        #region 绘图模式

        public bool ScaleActivated { get; set; } = false;
        public bool DrawActivated { get; set; } = false;
        public bool MultiActivated { get; set; } = false;

        public bool NoActivated { get { return !(ScaleActivated || DrawActivated || MultiActivated); } }

        public bool IsScaleAble { get { return ScaleActivated || (NoActivated && ImageLoaded); } }
        public bool IsDrawAble { get { return DrawActivated || (NoActivated && ScaleSet); } }
        public bool IsMultiAble { get { return MultiActivated || (NoActivated && ScaleSet); } }

        void RaiseUIPropertyChanged()
        {
            RaisePropertyChangedEvent("NoActivated");
            RaisePropertyChangedEvent("IsScaleAble");
            RaisePropertyChangedEvent("IsDrawAble");
            RaisePropertyChangedEvent("IsMultiAble");
            RaisePropertyChangedEvent("Hint");
            RaisePropertyChangedEvent("ScaleSet");
        }

        public string Hint { get; set; } = string.Empty;

        public bool ImageLoaded { get; set; } = false;

        /// <summary>
        /// 指示针对当前图片的标尺是否已经设置
        /// </summary>
        public bool ScaleSet { get; set; } = false;

        public RecordMaker CurrentDrawer { get; private set; }

        public ObservableCollection<MeasureRecord> ScaleRecords { get; private set; } = new ObservableCollection<MeasureRecord>();

        public ObservableCollection<MeasureRecord> MeasureRecords { get; private set; } = new ObservableCollection<MeasureRecord>();

        #endregion

        #region 激活/取消

        /// <summary>
        /// 令进入绘图模式
        /// </summary>
        void StartDrawing(RecordMaker drwr)
        {
            CurrentDrawer = drwr;
            RaiseUIPropertyChanged();
        }
        /// <summary>
        /// 令取消绘图模式
        /// </summary>
        void CancelDrawing()
        {
            CurrentDrawer = null;
            Hint = "取消操作";
            if (ScaleActivated) ScaleActivated = false;
            if (DrawActivated) DrawActivated = false;
            if (MultiActivated) MultiActivated = false;

            foreach (var d in Dots)
            {
                DrawingPanel.Children.Remove(d);
            }
            Dots.Clear();

            RaiseUIPropertyChanged();
        }

        void FinishDrawing()
        {
            Hint = "操作完成";
            foreach (var d in Dots)
            {
                DrawingPanel.Children.Remove(d);
            }
            Dots.Clear();
            if (ScaleActivated)
            {
                var r = CurrentDrawer.GenRecord(ZoomScale, null);
                var dia = new DiaInput();
                dia.InputConfirmed += (v) =>
                {
                    //清除旧的scale痕迹
                    if (ScaleRecords.Count > 0)
                    {
                        var odd = ScaleRecords.First();
                        DrawingPanel.Children.Remove(odd.Attached);
                        ScaleRecords.Remove(odd);
                    }

                    r.Claim = v;
                    ScaleActivated = false;
                    ScaleRecords.Add(r);

                    ScaleSet = true;
                    DrawingPanel.Children.Add(r.Attached);
                    RaiseUIPropertyChanged();
                };
                dia.ShowDialog();
            }
            else
            {
                try
                {
                    var r = CurrentDrawer.GenRecord(ZoomScale, ScaleRecords.First());
                    MessageBox.Show($"新测量：{r.Claim}");
                    MeasureRecords.Add(r);
                    DrawingPanel.Children.Add(r.Attached);
                    if (DrawActivated) DrawActivated = false;
                    if (MultiActivated) MultiActivated = false;
                    RaiseUIPropertyChanged();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        #endregion

        #region 界面动作

        List<Path> Dots = new List<Path>();

        private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!NoActivated)
            {
                var p = e.GetPosition(DrawingPanel);
                if (!CurrentDrawer.TakePoint(p))
                {
                    FinishDrawing();
                }
                else
                {
                    var dot = new Path()
                    {
                        Fill = new SolidColorBrush(Colors.Blue),
                        Data = new EllipseGeometry()
                        {
                            Center = p,
                            RadiusX = Configuration.Default.AsisPointSize * (Configuration.Default.AsisZoom ? ZoomScale : 1),
                            RadiusY = Configuration.Default.AsisPointSize * (Configuration.Default.AsisZoom ? ZoomScale : 1)
                        }
                    };
                    Dots.Add(dot);
                    DrawingPanel.Children.Add(dot);
                }
            }
        }

        private void Grid_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!NoActivated)
            {
                CancelDrawing();
            }
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape && !NoActivated)
            {
                CancelDrawing();
            }
            else if (e.Key == Key.Enter && MultiActivated)
            {
                FinishDrawing();
            }
        }

        #endregion

        #region 功能响应

        private void BtnScale_Click(object sender, RoutedEventArgs e)
        {
            if (ScaleActivated)
            {
                CancelDrawing();
            }
            else
            {
                ScaleActivated = true;
                Hint = "拾取标尺";
                StartDrawing(new LineRecordMaker());
            }
        }

        private void BtnMeasure_Click(object sender, RoutedEventArgs e)
        {
            if (DrawActivated)
            {
                CancelDrawing();
            }
            else
            {
                DrawActivated = true;
                Hint = "量取直线";
                StartDrawing(new LineRecordMaker());
            }
        }

        private void BtnMulti_Click(object sender, RoutedEventArgs e)
        {
            if (MultiActivated)
            {
                FinishDrawing();
            }
            else
            {
                MultiActivated = true;
                Hint = "量取多段";
                StartDrawing(new MultiRecordMaker());
            }
        }

        #endregion

        #region 记录显示

        private void RecordChecked(object sender, RoutedEventArgs e)
        {
            var rec = (sender as FrameworkElement).DataContext as MeasureRecord;
            rec.Attached.Visibility = Visibility.Visible;
        }

        private void RecordUnchecked(object sender, RoutedEventArgs e)
        {
            var rec = (sender as FrameworkElement).DataContext as MeasureRecord;
            rec.Attached.Visibility = Visibility.Hidden;
        }

        #endregion

        private void TextBlock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start("https://gitee.com/heroius/Heroius.BlueMeasure/wikis");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ClearRecords(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("确定清除记录？", "警告", MessageBoxButton.OKCancel, MessageBoxImage.Warning) == MessageBoxResult.OK)
            {
                foreach (var r in MeasureRecords)
                {
                    DrawingPanel.Children.Remove(r.Attached);
                }
                MeasureRecords.Clear();
            }
        }

        private void BtnConfig_Click(object sender, RoutedEventArgs e)
        {
            new ConfigWindow() { Owner = this }.ShowDialog();
        }

    }
}
